package com.litbw.dbbackend;

import java.util.Map;

import com.litbw.dbbackend.DBManager.FieldType;

/**
 * The AbstractDBAdapter class houses common functionality between the
 * DBAdapters... WIP
 * 
 * @author Michael Morris
 *
 */
public class AbstractDBAdapter {
	/** The database where all data will be saved. **/
	public static String DB_PATH = "alldata.db";
	
	/** The table that will be used for Users. **/
	protected final String table_name;
	
	/** The DBManager instance used to connect and run queries. **/
	protected DBManager db = null;
	
	/** The fields to use for the table access. **/
	private Map<String, FieldType> fields = null;

	/** String field identifier for Primary Key. **/
	private String primary = null;
	
	/** Flag used to control autoincrement of Primary Key. **/
	private boolean autoincrement = false;
	
	protected AbstractDBAdapter(final String the_table_name) {
		if (the_table_name == null || the_table_name.isEmpty())
			throw new IllegalArgumentException("cannot access/create empty/null table");
		
		table_name = the_table_name;
		db = new DBManager(DB_PATH);
	}
	
	/**
	 * Set the primary key of the subclass' table.
	 * @param the_primary The String field name of the primary key.
	 */
	protected final void setPrimary(final String the_primary) {
		
		if (the_primary == null || the_primary.isEmpty())
			throw new IllegalArgumentException("cannot set primary to null/nothing");
		
		primary = the_primary;
		
	}
	
	/**
	 * Set the auto increment flag for primary key.
	 * @param flag True if the primary key should be auto incremented, false
	 * otherwise.
	 */
	protected final void setAutoIncrement(final boolean flag) {
		autoincrement = flag;
	}
	
	/**
	 * Set the fields used in the subclass' table.
	 * @param the_fields A map containing name/type pairs.
	 */
	protected final void setTableFields(final Map<String, FieldType> the_fields) {
		
		fields = the_fields;
		
	}
	
	/**
	 * Private method for setting up connection before a query/update.
	 * @return True if the connection is fully setup and ready for use.
	 */
	protected boolean checkDatabaseConnection() {
		
		if (fields == null || db == null || primary == null)
			return false;
		
		// Connect to the instance.
		boolean rtn = db.connect();
		
		// If connected attempt to make/or-not the table (doesn't override so this is ok).
		if (rtn) {
					
			// Create table with above fields using the 'name' field as primary key and NOT autoincrementing.
			db.createTable(table_name, fields, primary, autoincrement);
			
		}
			
		return rtn;
	
	}
	
	/** 
	 * A convenience method for disconnecting from the database.
	 */
	protected void disconnect() {
		if (db != null)
			db.disconnect();
	}
	
	/**
	 * Retrieve an SQL compatible String from the given object, or
	 * NULL if the object will not be converted correctly.
	 * @param obj The object to retrieve string for.
	 * @return An String which can be used in SQL statement or null.
	 */
	public static String sqlAcceptable(final Object obj) {
		
		if (obj == null) {
			return "NULL";
		} else if (obj instanceof Integer || obj instanceof Double || obj instanceof Float) {
			return obj.toString();
		} else if (obj instanceof String) {
			return "'" + obj.toString() + "'";
		} else {
			throw new IllegalArgumentException("invalid type to be inserted in to sql statement");
		}
		
	}

}
